using Admin2025.Application.DTOs;
using BackOffice.Application.Services;
using Backoffice.Application.Common;
using Backoffice.Domain.Entities.App;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Backoffice.Domain.Repositories;

namespace BackOffice.Application.Services
{
    public class PermissionService : IPermissionService
    {
        private readonly IRepository<AppRolePermission> _rolePermissionRepo;
        private readonly IRepository<AppMenu> _menuRepo;
        private readonly IRepository<AppRole> _roleRepo;
        private readonly IRepository<AppPermission> _permissionRepo;

        public PermissionService(
            IRepository<AppRolePermission> rolePermissionRepo,
            IRepository<AppMenu> menuRepo,
            IRepository<AppRole> roleRepo,
            IRepository<AppPermission> permissionRepo)
        {
            _rolePermissionRepo = rolePermissionRepo;
            _menuRepo = menuRepo;
            _roleRepo = roleRepo;
            _permissionRepo = permissionRepo;
        }

        public async Task<ApiResult> AssignPermissionToRoleAsync(Guid roleId, Guid permissionId)
        {
            var role = await _roleRepo.GetByIdAsync(roleId);
            if (role == null)
            {
                return ApiResult.Fail("角色未找到", 3002);
            }

            var permission = await _permissionRepo.GetByIdAsync(permissionId);
            if (permission == null)
            {
                return ApiResult.Fail("权限未找到", 3002);
            }

            var list = await _rolePermissionRepo.GetAllAsync();
            var existingPermission = list.FirstOrDefault(rp => rp.RoleId == roleId && rp.PermissionId == permissionId);
            
            if (existingPermission != null)
            {
                return ApiResult.Fail("权限已分配", 3003);
            }

            var rolePermission = new AppRolePermission(role, permission);
            await _rolePermissionRepo.CreateAsync(rolePermission);
            return ApiResult.Success(rolePermission, "分配权限成功");
        }

        public async Task<ApiResult> RemovePermissionFromRoleAsync(Guid roleId, Guid permissionId)
        {
            var role = await _roleRepo.GetByIdAsync(roleId);
            if (role == null)
            {
                return ApiResult.Fail("角色未找到", 3002);
            }

            var permission = await _permissionRepo.GetByIdAsync(permissionId);
            if (permission == null)
            {
                return ApiResult.Fail("权限未找到", 3002);
            }

            var list = await _rolePermissionRepo.GetAllAsync();
            var rolePermission = list.FirstOrDefault(rp => rp.RoleId == roleId && rp.PermissionId == permissionId);            if (rolePermission == null)
            {
                return ApiResult.Fail("权限未分配", 3004);
            }

            await _rolePermissionRepo.DeleteAsync(rolePermission.Id);
            return ApiResult.Success(rolePermission, "移除权限成功");
        }

        public async Task<ApiResult> GetPermissionsByRoleAsync(Guid roleId)
        {
            var role = await _roleRepo.GetByIdAsync(roleId);
            if (role == null)
            {
                return ApiResult.Fail("角色未找到", 3002);
            }

            var all = await _rolePermissionRepo.GetAllAsync();
            var permissions = all
                .Where(rp => rp.RoleId == roleId)
                .Select(rp => rp.Permission)
                .ToList();

            return ApiResult.Success(permissions, "获取权限成功");
        }

        public async Task<ApiResult> GetMenusByRoleAsync(Guid roleId)
        {
            var role = await _roleRepo.GetByIdAsync(roleId);
            if (role == null)
            {
                return ApiResult.Fail("角色未找到", 3002);
            }

            var menus = (await _menuRepo.GetAllAsync())
            .Where(m => m.ParentId == null)
            .ToList();

            var rolePermissions = (await _rolePermissionRepo.GetAllAsync())
                                  .Where(rp => rp.RoleId == roleId)
                                  .Select(rp => rp.PermissionId)
                                  .ToList();

            var accessibleMenus = new List<AppMenu>();
            foreach (var menu in menus)
            {
                if (await HasMenuAccess(menu, rolePermissions))
                {
                    accessibleMenus.Add(menu);
                }
            }

            return ApiResult.Success(accessibleMenus, "获取菜单成功");
        }

        private async Task<bool> HasMenuAccess(AppMenu menu, List<Guid> rolePermissions)
        {
            var menuPermissions = (await _rolePermissionRepo.GetAllAsync())
                      .Where(rp => rp.RoleId == menu.Id)
                      .Select(rp => rp.PermissionId)
                      .ToList();

            return menuPermissions.Any(mp => rolePermissions.Contains(mp));
        }
    }
}